package linkcut;

public class AuxVertex<V> {
	private V value;
	private AuxVertex<V> parent;
	private AuxVertex<V> left;
	private AuxVertex<V> right;
	private TypeAsChild type;	
	private AuxVertex<V> pathParent;
	
	public AuxVertex<V> getPathParent() {
		return pathParent;
	}
	
	public void setPathParent(AuxVertex<V> pp) {
		this.pathParent = pp;
	}
	
	public AuxVertex() {
		this.value = null;
		this.parent = null;
		this.left = null;
		this.right = null;
		this.type = TypeAsChild.root;
	}
	
	public AuxVertex(V value) {
		this.value = value;
		this.parent = null;
		this.left = null;
		this.right = null;
		this.type = TypeAsChild.root;
	}
	
	public AuxVertex(V value, AuxVertex<V> left, AuxVertex<V> right) {
		this.value = value;
		this.parent = null;
		this.type = TypeAsChild.root;
		attachLeft(left);
		attachRight(right);
	}
	
	public AuxVertex(AuxVertex<V> left, AuxVertex<V> right) {
		this.value = null;
		this.parent = null;
		this.type = TypeAsChild.root;
		attachLeft(left);
		attachRight(right);
	}

	public boolean isRoot() {
		if (type == null) throw new AssertionError();
		if (type == TypeAsChild.root) {
			if (parent != null) throw new IllegalStateException();
			return true;
		} else {
			if (parent == null) throw new IllegalStateException();
			return false;
		}
	}

	public AuxVertex<V> getLeft() {
		return left;
	}
	
	public AuxVertex<V> getRight() {
		return right;
	}
	
	public AuxVertex<V> getParent() {
		return parent;
	}

	public TypeAsChild getType() {
		return type;
	}

	public V getValue() {
		return value;
	}
	
	public void setValue(V val) {
		this.value = val;
	}

	public void attachRight(AuxVertex<V> v) {
		if (v == this) throw new IllegalArgumentException("Attaching itself");
		if (v.parent != null) throw new IllegalArgumentException("Attaching not a root");
		if (v.type != TypeAsChild.root) throw new IllegalArgumentException("Attaching not a root");
		if (this.right != null) throw new IllegalStateException("Right is not empty");
		this.right = v;
		v.parent = this;
		v.type = TypeAsChild.right;
	}
	
	public void attachLeft(AuxVertex<V> v) {
		if (v == this) throw new IllegalArgumentException("Attaching itself");
		if (v.parent != null) throw new IllegalArgumentException("Attaching not a root");
		if (v.type != TypeAsChild.root) throw new IllegalArgumentException("Attaching not a root");
		if (this.left != null) throw new IllegalStateException("Left is not empty");
		this.left = v;
		v.parent = this;
		v.type = TypeAsChild.left;
	}
	
	public void detachFromParent() {
		if (parent == null) throw new IllegalStateException("Detaching not a child");
		if (type == TypeAsChild.left) {
			if (parent.left != this) throw new IllegalStateException("Type is wrong (2)");
			parent.left = null;
			parent = null;
			type = TypeAsChild.root;
		} else if (type == TypeAsChild.right) {
			if (parent.right != this) throw new IllegalStateException("Type is wrong (3)"); 
			parent.right = null;
			parent = null;
			type = TypeAsChild.root;
		} else throw new IllegalStateException("Type is wrong (1)");
	}
	
	@Override
	public String toString() {
		if (value == null) {
			return "null";
		}
		return value.toString();
	}

}
